package com.google.gsaguide.volley;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v4.util.LruCache;

import com.android.volley.toolbox.ImageLoader;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * This class manages the BitmapCache.
 * @author Felipe Porge Xavier - http://www.felipeporge.com
 */
public class LruBitmapCache extends LruCache<String, Bitmap> implements
        ImageLoader.ImageCache {

    private File mCacheDir;

    /**
     * Return the max Lru cache size;
     * @return - Max Lru cache size
     */
    public static int getDefaultLruCacheSize() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;

        return cacheSize;
    }


    public LruBitmapCache(int sizeInKiloBytes) {
        super(sizeInKiloBytes);
    }

    public LruBitmapCache(Context mContext) {
        this(getDefaultLruCacheSize());

        //Find the dir to save cached images
        if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
            mCacheDir = new File(android.os.Environment.getExternalStorageDirectory() + "/Android/data/com.google.gsaguide/", "cache");
        else
            mCacheDir = mContext.getCacheDir();

        // If the cache directory do not exists, create it.
        if(!mCacheDir.exists())
            mCacheDir.mkdirs();
    }

    /**
     * This method returns the size of an Bitmap.
     * @param key
     * @param value - Bitmap
     * @return - Size of this bitmap.
     */
    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }

    @Override
    public Bitmap getBitmap(String url) {

        //I identify images by hashcode.
        String filename = String.valueOf(url.hashCode());
        File file = new File(mCacheDir, filename);

        // Get a bitmap from file.
        int size = (int) file.length();
        byte[] sByteArray = new byte[size];
        try {
            BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
            buf.read(sByteArray, 0, sByteArray.length);
            buf.close();
            Bitmap bp = BitmapFactory.decodeByteArray(sByteArray, 0, sByteArray.length);
            if(bp != null)
                return bp;
            else
                throw new Exception();
        } catch (Exception e) {
            return get(url);
        }
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        if(bitmap == null)
            return;

        // Put this bitmap in the cache.
        try {
            String filename = String.valueOf(url.hashCode());
            File f = new File(mCacheDir, filename);
            f.createNewFile();

            FileOutputStream stream = new FileOutputStream(f);
            ByteArrayOutputStream outstream = new ByteArrayOutputStream();

            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outstream);
            byte[] byteArray = outstream.toByteArray();

            stream.write(byteArray);
            stream.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * This method allows to clear the image file cache.
     * @param context - Context of the current activity.
     */
    public static void clear(Context context){
        File cacheDir;

        //Find the dir to save cached images
        if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
            cacheDir = new File(android.os.Environment.getExternalStorageDirectory() + "/Android/data/com.google.gsaguide/", "cache");
        else
            cacheDir = context.getCacheDir();
        if(!cacheDir.exists())
            cacheDir.mkdirs();

        // Delete all the files.
        File[] files = cacheDir.listFiles();
        if(files == null)
            return;
        for(File f:files)
            f.delete();
    }
}
